const WebSocket = require('ws');
const jwtUtils = require('../utils/jwtUtils');
const wsConfig = require('../config/ws');

class WebSocketServer {
  constructor(server) {
    this.wss = new WebSocket.Server({ server });
    this.clients = new Map(); // 存储用户ID到WebSocket连接的映射
    this.setupEventListeners();
  }

  setupEventListeners() {
    // 处理新连接
    this.wss.on('connection', (ws, req) => {
      // 从请求中提取用户信息
      const userId = this.extractUserIdFromRequest(req);
      
      if (userId) {
        // 存储连接
        this.clients.set(userId, ws);
        
        console.log(`用户 ${userId} 已连接，当前连接数: ${this.clients.size}`);
        
        // 设置心跳定时器
        const heartbeatInterval = setInterval(() => {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({ type: wsConfig.messageTypes.HEARTBEAT }));
          }
        }, wsConfig.heartbeatInterval);
        
        // 处理消息
        ws.on('message', (message) => this.handleMessage(userId, message));
        
        // 处理关闭
        ws.on('close', () => {
          clearInterval(heartbeatInterval);
          this.handleDisconnect(userId);
        });
        
        // 处理错误
        ws.on('error', (error) => {
          console.error(`WebSocket错误 (${userId}):`, error);
          clearInterval(heartbeatInterval);
          this.handleDisconnect(userId);
        });
        
        // 发送连接成功消息
        this.sendToUser(userId, {
          type: wsConfig.messageTypes.SYSTEM,
          content: '连接成功',
          timestamp: new Date().toISOString()
        });
      } else {
        // 拒绝未授权的连接
        ws.close(1008, '未授权的连接');
      }
    });

    // 处理服务器错误
    this.wss.on('error', (error) => {
      console.error('WebSocket服务器错误:', error);
    });
  }

  /**
   * 从请求中提取用户ID
   * @param {http.IncomingMessage} req - HTTP请求对象
   * @returns {string|null} - 用户ID或null
   */
  extractUserIdFromRequest(req) {
    try {
      // 从查询参数获取token
      const url = new URL(req.url, `http://${req.headers.host}`);
      const token = url.searchParams.get('token');
      
      if (!token) {
        return null;
      }
      
      // 验证token
      const decoded = jwtUtils.verifyAccessToken(token);
      return decoded ? decoded.userId : null;
    } catch (error) {
      console.error('提取用户ID失败:', error);
      return null;
    }
  }

  /**
   * 处理接收到的消息
   * @param {string} userId - 发送消息的用户ID
   * @param {Buffer} messageBuffer - 消息缓冲区
   */
  handleMessage(userId, messageBuffer) {
    try {
      // 检查消息大小
      if (messageBuffer.length > wsConfig.maxMessageSize) {
        this.sendToUser(userId, {
          type: wsConfig.messageTypes.SYSTEM,
          content: '消息过大',
          error: true,
          timestamp: new Date().toISOString()
        });
        return;
      }
      
      // 解析消息
      const message = JSON.parse(messageBuffer.toString());
      
      // 处理心跳响应
      if (message.type === wsConfig.messageTypes.HEARTBEAT) {
        return;
      }
      
      console.log(`收到来自 ${userId} 的消息:`, message);
      
      // 根据消息类型处理
      switch (message.type) {
        case wsConfig.messageTypes.CHAT:
          this.handleChatMessage(userId, message);
          break;
        case wsConfig.messageTypes.NOTIFICATION:
          this.handleNotificationMessage(userId, message);
          break;
        default:
          // 未知消息类型
          this.sendToUser(userId, {
            type: wsConfig.messageTypes.SYSTEM,
            content: '未知的消息类型',
            error: true,
            timestamp: new Date().toISOString()
          });
      }
    } catch (error) {
      console.error(`处理消息失败 (${userId}):`, error);
      this.sendToUser(userId, {
        type: wsConfig.messageTypes.SYSTEM,
        content: '消息处理失败',
        error: true,
        timestamp: new Date().toISOString()
      });
    }
  }

  /**
   * 处理聊天消息
   * @param {string} userId - 发送消息的用户ID
   * @param {Object} message - 消息对象
   */
  handleChatMessage(userId, message) {
    // 验证消息格式
    if (!message.receiverId || !message.content) {
      this.sendToUser(userId, {
        type: wsConfig.messageTypes.SYSTEM,
        content: '消息格式错误',
        error: true,
        timestamp: new Date().toISOString()
      });
      return;
    }

    // 构建响应消息
    const responseMessage = {
      type: wsConfig.messageTypes.CHAT,
      senderId: userId,
      receiverId: message.receiverId,
      content: message.content,
      timestamp: new Date().toISOString()
    };

    // 发送给接收者
    this.sendToUser(message.receiverId, responseMessage);
    
    // 发送确认给发送者
    this.sendToUser(userId, {
      ...responseMessage,
      status: 'delivered'
    });
  }

  /**
   * 处理通知消息
   * @param {string} userId - 发送消息的用户ID
   * @param {Object} message - 消息对象
   */
  handleNotificationMessage(userId, message) {
    // 这里可以添加更复杂的通知处理逻辑
    this.broadcast({
      type: wsConfig.messageTypes.NOTIFICATION,
      senderId: userId,
      content: message.content,
      timestamp: new Date().toISOString()
    }, userId);
  }

  /**
   * 处理断开连接
   * @param {string} userId - 用户ID
   */
  handleDisconnect(userId) {
    this.clients.delete(userId);
    console.log(`用户 ${userId} 已断开连接，当前连接数: ${this.clients.size}`);
  }

  /**
   * 发送消息给特定用户
   * @param {string} userId - 用户ID
   * @param {Object} message - 消息对象
   */
  sendToUser(userId, message) {
    const client = this.clients.get(userId);
    
    if (client && client.readyState === WebSocket.OPEN) {
      try {
        client.send(JSON.stringify(message));
        return true;
      } catch (error) {
        console.error(`发送消息给 ${userId} 失败:`, error);
        this.handleDisconnect(userId);
        return false;
      }
    }
    
    return false;
  }

  /**
   * 广播消息给所有连接的用户
   * @param {Object} message - 消息对象
   * @param {string} [excludeUserId] - 排除的用户ID
   */
  broadcast(message, excludeUserId) {
    this.clients.forEach((client, userId) => {
      if (userId !== excludeUserId && client.readyState === WebSocket.OPEN) {
        try {
          client.send(JSON.stringify(message));
        } catch (error) {
          console.error(`广播消息给 ${userId} 失败:`, error);
          this.handleDisconnect(userId);
        }
      }
    });
  }

  /**
   * 获取连接状态
   * @returns {Object} - 连接状态信息
   */
  getStatus() {
    return {
      connectedUsers: this.clients.size,
      users: Array.from(this.clients.keys()),
      serverTime: new Date().toISOString()
    };
  }
}

module.exports = WebSocketServer;